﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Collections;

namespace PortTcpClient
{
    /// <summary>
    /// 
    /// </summary>
    public class PortTcpClient:IPort.ILogicPort
    {
        List<byte> DataCancle = new List<byte>();
        //opencv openxml opengl

        /// <summary>
        /// 定义端口实例
        /// </summary>
        Socket _port = null;

        public PortTcpClient()
        {
            if (_port == null)
                _port = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        }


        /// <summary>
        /// 构造
        /// </summary>
        /// <param name="threadSleepTime"></param>
        /// <param name="portOutTimeVal"></param>
        public PortTcpClient(string cfg)
        {
            if (_port == null)
                _port = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            this.Open(cfg);
        }
       
        /// <summary>
        /// 打开端口的操作
        /// </summary>
        /// <param name="portCfg"></param>
        public bool Open(string portCfg)
        {
            try
            {
                if (portCfg == null)
                {
                    this.IsOpen = false;
                    return false;                 
                }
                string[] portparams = portCfg.Split(',');
                if(portparams.Length!=6)
                { 
                    this.IsOpen = false;
                    return false; 
                }
                this.PortName = portparams[0];
                this.PortArgs = portCfg;
                string[] args = portparams[0].Split(':');
                if (args.Length != 2) return false;
                string ip = args[0];
                int port =Convert.ToInt32( args[1]);
                if (string.IsNullOrEmpty(ip))
                {
                    this.IsOpen = false;
                    return false;
                }
                if(port<=0||port>=65536)
                {
                    this.IsOpen = false;
                    return false;
                }
                this.Close("");
                if(_port==null)
                    _port = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                IPAddress address =  IPAddress.Parse(ip);
                this._port.BeginConnect(address, port, new AsyncCallback(EndConnect), this._port);
                
                this.IsOpen=false;
                return true;
            }
            catch (Exception ex)
            {
                //mIOMannager.LogManager.LogHelper.WriteFile(this.Flag, ex.Message);
                //throw(ex);
                return false;

            }
        
        }
        byte[] _RecvieBuffer = new byte[1024];
        /// <summary>
        /// 
        /// </summary>
        /// <param name="res"></param>
        void EndConnect(IAsyncResult res)
        {
            try
            {
                Socket port = res.AsyncState as Socket;
                if (port == null) return;
                port.EndConnect(res);
                this.IsOpen = true;
                //portDebugManager.AddMsg(this.Name + "-" + "Connected OK!  " + DateTime.Now.ToString() + ":" + DateTime.Now.Millisecond.ToString());
                this.OnPortData("CONN-OK", null);
                port.BeginReceive(_RecvieBuffer, 0, _RecvieBuffer.Length, SocketFlags.None, out _Error, new AsyncCallback(EndRecvie), this._port);
               //transCMDBase inncmd = new   transCMDBase ();
               // if (inncmd == null) return;
               // StateObject innState = new StateObject();
               // innState.Handler = this._port;
               // inncmd.AysnState = innState;
               // inncmd.ID = "DeviceAutoUpload";
               // this._currentCMD = inncmd;
               // portDebugManager.AddMsg(this.Name + "-" + _SendFalg + "  Over  " + DateTime.Now.ToString() + ":" + DateTime.Now.Millisecond.ToString());
               // inncmd.AysnState.Handler.BeginReceive(inncmd.AysnState.Buffer, 0, inncmd.AysnState.Buffer.Length, SocketFlags.None, new AsyncCallback(EndRecvie), inncmd);



            }
            catch (Exception ex)
            {
                this.OnPortData("CONN-ERR", null);
                this.IsOpen = false;
                //mIOMannager.LogManager.LogHelper.WriteFile(this.Flag, ex.Message);
            }
        }


        bool bAutoRead = false;
        string _SendFalg = "Send:";
        string _ReciveFlag = "Recive:";
        SocketError _Error = new SocketError();
        
        /// <summary>
        /// 
        /// </summary>
        /// <param name="res"></param>
        void EndSend(IAsyncResult res)
        {
            try
            {
                this._port.EndSend(res);
                //portDebugManager.AddMsg(this.Name + "-" + _SendFalg + "  Over  " + DateTime.Now.ToString() + ":" + DateTime.Now.Millisecond.ToString());
              //  cmd.AysnState.Handler.BeginReceive(cmd.AysnState.Buffer, 0, cmd.AysnState.Buffer.Length, SocketFlags.None, new AsyncCallback(EndRecvie), cmd);

            }
            catch (Exception ex)
            {
                //mIOMannager.LogManager.LogHelper.WriteFile(this.Flag, ex.Message);
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="res"></param>
        void EndRecvie(IAsyncResult res)
        {
            try
            {
                Socket cmd = res.AsyncState as Socket ;
                if (cmd == null) return;
                int count = cmd.EndReceive(res);
                if (count > 0)
                {
                    byte[] innlist = new byte[count];
                    Array.Copy(this._RecvieBuffer, 0, innlist, 0, innlist.Length);
                    IOHelper.DebugMsg.Log(this.PortName+"  Recvied Data :"+BitConverter.ToString(innlist));
                    if (this.OnPortData != null)
                    {
                        this.OnPortData(this.PortName,innlist);
                    }
                    else
                    {
                        lock (this.DataCancle)
                        {
                            this.DataCancle.AddRange(innlist);
                        }
                    }
                }
                //port.BeginReceive(_RecvieBuffer, 0, _RecvieBuffer.Length, SocketFlags.None, out _Error, new AsyncCallback(EndRecvie), this._port);
                this._port.BeginReceive(this. _RecvieBuffer, 0, this._RecvieBuffer.Length, SocketFlags.None, out _Error, new AsyncCallback(EndRecvie), this._port);

            }
            catch (Exception ex)
            {
                //mIOMannager.LogManager.LogHelper.WriteFile(this.Flag, ex.Message);
            }
        }


        public bool Close(string args)
        {
            if (_port == null) return false;
            if (this.IsOpen) _port.Close();
            this.IsOpen = false;
            return true;
        }

        public byte[] ReadData()
        {
            lock (this.DataCancle)
            {
                byte[] buffer = this.DataCancle.ToArray();
                this.DataCancle.Clear();
                return buffer;
            }
        }

        public bool WriteData(byte[] buffer)
        {
            try
            {
                
                if (this._port == null) return false;
                if (!this.IsOpen) return false;
                bAutoRead = false;
                IOHelper.DebugMsg.Log(this.PortName + "  Write Data :" + BitConverter.ToString(buffer));
                this._port.BeginSend(buffer, 0, buffer.Length, SocketFlags.None, out _Error, new AsyncCallback(EndSend), this._port);
                if (_Error != SocketError.Success)
                {
                    if (_Error == SocketError.ConnectionAborted)
                    {
                        this.IsOpen = false;
                    }
                }

                return true;
            }
            catch (Exception ex)
            {
                //mIOMannager.LogManager.LogHelper.WriteFile(this.Flag, ex.Message);
                return false;
            }
        }

        public event IPort.OnPortDataHandler OnPortData;

        string _PortName = string.Empty;

        public string PortName
        {
            get
            {
                return _PortName;
            }
            set
            {
                _PortName=value;
            }
        }

        string _portAegs = string.Empty;

        public string PortArgs
        {
            get
            {
                return _portAegs;
            }
            set
            {
                _portAegs=value;
            }
        }

        public int BytesCanRead
        {
            get {return this.DataCancle.Count; }
        }

        bool _IsOpen = false;

        public bool IsOpen
        {
            get {return _IsOpen  ; }
            set { _IsOpen = value; }
        }
    }
}
